package com.fingard.dsp.bank.directbank.klb01;


import cfca.sadk.algorithm.common.Mechanism;
import cfca.sadk.lib.crypto.JCrypto;
import cfca.sadk.lib.crypto.Session;
import cfca.sadk.util.CertUtil;
import cfca.sadk.util.KeyUtil;
import cfca.sadk.util.Signature;
import cfca.sadk.x509.certificate.X509Cert;
import com.fingard.constant.Format;
import com.fingard.dsp.DSPSet;
import com.fingard.dsp.bank.directbank.DirectBase;
import com.fingard.dsp.bank.directbank.FailCode;
import com.fingard.io.FileHelper;
import com.fingard.net.WebRequest;
import com.fingard.text.StringHelper;
import com.fingard.util.TransIDHelper;
import com.fingard.xml.XmlTextWriter;

import java.security.PrivateKey;
import java.util.Date;

public class KLB01Base extends DirectBase  {
	protected String bnkVersion = "0.0.0.1";  //版本
	protected String bank = "";  //银行ID
	protected String bnkOrgId = "";  //组织机构代码
	protected String bnkoOrgName = "";//组织机构名称
	protected String bnkLoginId = " ";//接入用户
	protected String bnkLoginPassword = " ";//用户密码
	protected String bnkLoginCert = " ";		//用户证书ID
	protected String bnkTxCode = "";      //交易代码
	protected String bnkTxPackNo = "";//指令包序列号

    private static TransIDHelper idHelper = new TransIDHelper(1, 999);
    protected String getQryTransID() {
        Date tmpDateNow = new Date();
        return Format.DateTime12Year2Format.format(tmpDateNow) + idHelper.getNextIDStr();
    }

	protected void writeCommonHeader(XmlTextWriter xmlWriter) throws Exception {
		if (StringHelper.isNullOrEmpty(bnkVersion)) {
			throw new Exception("未赋值bnkVersion");
		}
		if (StringHelper.isNullOrEmpty(bank)) {
			throw new Exception("未赋值bank");
		}
		if (StringHelper.isNullOrEmpty(bnkOrgId)) {
			throw new Exception("未赋值bnkOrgId");
		}
		if (StringHelper.isNullOrEmpty(bnkoOrgName)) {
			throw new Exception("未赋值bnkoOrgName");
		}
		if (StringHelper.isNullOrEmpty(bnkTxCode)) {
			throw new Exception("未赋值bnkTxCode");
		}
		if (StringHelper.isNullOrEmpty(bnkTxPackNo)) {
			throw new Exception("未赋值bnkTxPackNo");
		}

		xmlWriter.writeStartDocByDeclaration("<?xml version=\"1.0\" encoding=\"GBK\"?>");
		xmlWriter.writeStartElement("root");
		xmlWriter.writeStartElement("head");
		xmlWriter.writeElementString("Version", bnkVersion);
		xmlWriter.writeElementString("Bank", bank);
		xmlWriter.writeElementString("OrgId", bnkOrgId);//组织机构代码
		xmlWriter.writeElementString("OrgName", bnkoOrgName);//组织机构名称
		xmlWriter.writeElementString("LoginId", bnkLoginId);
		xmlWriter.writeElementString("LoginPassword", bnkLoginPassword);
		xmlWriter.writeElementString("LoginCert", bnkLoginCert);
		xmlWriter.writeElementString("TxCode", bnkTxCode);
		Date tmpDateNow = new Date();
		xmlWriter.writeElementString("TxDate", Format.Date10Format.format(tmpDateNow));
		xmlWriter.writeElementString("TxTime", Format.Time6Format.format(tmpDateNow));
		xmlWriter.writeElementString("TxPackNo", bnkTxPackNo);

		xmlWriter.writeEndElement();

		
	}

	protected String getCharset() {
		return getBankConfig().getCharset("GBK");
	}

	protected String[] sendToBank(String p_reqStr) throws Exception {
		// TODO Auto-generated method stub
		String[] retStr = new String[] { "", "" };
		String tmpRequestURL = bankFront.serverURL;
		WriteBankLogLn("1.提交银行的地址：" + tmpRequestURL);
		StringBuilder tmpSb = new StringBuilder();
		String signXml=getDataSignData(p_reqStr);
		String signResult=signnatrue(signXml);	
		WriteBankLogLn("2.签名结果");
		if(signResult!=null && tmpSb.length()==0){
			int indexIns = p_reqStr.indexOf("</root>");
			StringBuilder tmpSbPck = new StringBuilder();
			tmpSbPck.append(p_reqStr.substring(0, indexIns));
			tmpSbPck.append("<signtext>");
			tmpSbPck.append(signResult);
			tmpSbPck.append("</signtext>");
			tmpSbPck.append(p_reqStr.substring(indexIns));
			WriteBankLogStep2(tmpSbPck);
			WebRequest tmpWebRequest = new WebRequest(tmpRequestURL,this.bankFront,this.sbLog);
			tmpWebRequest.setConnectTimeout(100000);
			tmpWebRequest.setRequestProperty("Content-Type", "application/stream");
			//tmpWebRequest.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
			tmpWebRequest.setRequestProperty("connection", "Close");
			byte[] tmpUpBytes = tmpSbPck.toString().getBytes(getCharset());
			retStr = tmpWebRequest.upload(tmpUpBytes, getCharset());
			WriteBankLogStep3(retStr[1]);
			if(retStr[0].length() == 0){
				int tmpIndex = retStr[1].indexOf("<");
				if(tmpIndex > 0){
					retStr[1] = retStr[1].substring(tmpIndex);
				}
			}
		}
		else{
			retStr[0] = FailCode.E9981;
			retStr[1] = "签名失败：" + tmpSb.toString();
		}
		return retStr;
	}

	public String getDataSignData(String p_reqStr) {
    
        String data=p_reqStr.substring(p_reqStr.indexOf("<head>") , p_reqStr.indexOf("</body>")+7);
        return data;
    }
	
	

	// 处理数据签名
	protected String signnatrue(String signXml) throws Exception {
		// 步骤1 加密库初始化
		String deviceName = JCrypto.JSOFT_LIB;
        JCrypto.getInstance().initialize(deviceName, null);
        Session session = JCrypto.getInstance().openSession(deviceName);

		// 步骤2 构建证书对象
        String pfxFileData = getBankConfig().getValueAsString("ownKeyStorePath");
        pfxFileData = DSPSet.replaceFilePath(pfxFileData);
        if(!FileHelper.existFile(pfxFileData)){
			WriteBankLogLn("证书文件"+pfxFileData+"不存在");
		}
		String pfxFilePwd = getBankConfig().getValueAsString("ownKeyPassword");
		X509Cert signCert;
		PrivateKey privateKey;
		String signAlg;

			signCert = CertUtil.getCertFromPFX(pfxFileData, pfxFilePwd);
			// 步骤3 获得私钥对象
			privateKey = KeyUtil.getPrivateKeyFromPFX(pfxFileData, pfxFilePwd);
			signAlg = Mechanism.SHA256_RSA;
	

		// 组装签名报文
	
		StringBuilder stringBuilder = new StringBuilder();
		stringBuilder.append(signXml);

		 Signature signKit = new Signature();
		 byte[] sourceData = stringBuilder.toString().getBytes("GBK");
		 
		 byte[] signedData = signKit.p7SignMessageDetach(signAlg, sourceData, privateKey, signCert, session);
		 String singtext = new String(signedData);
		 WriteBankLogLn("签名返回的结果：" + singtext);

		 return singtext;
	}
	
	
	/*protected String signnatrue(String signXml) throws Exception {
		// 步骤1 加密库初始化
		String deviceName = JCrypto.JSOFT_LIB;
		JCrypto.getInstance().initialize(deviceName, null);
		Session session = JCrypto.getInstance().openSession(deviceName);

		// 步骤2 构建证书对象
		String pfxFileData = getBankConfig().getValueAsString("ownKeyStorePath");
		pfxFileData = DSPSet.replaceFilePath(pfxFileData);
		if(!FileHelper.existFile(pfxFileData)){
			WriteBankLogLn("证书文件"+pfxFileData+"不存在");
		}
		String pfxFilePwd = getBankConfig().getValueAsString("ownKeyPassword");
		X509Cert signCert;
		PrivateKey privateKey;
		String signAlg;
		if(pfxFileData.toLowerCase().endsWith(".pfx")){
			signCert = CertUtil.getCertFromPFX(pfxFileData, pfxFilePwd);
			// 步骤3 获得私钥对象
			privateKey = KeyUtil.getPrivateKeyFromPFX(pfxFileData, pfxFilePwd);
			signAlg = Mechanism.SHA1_RSA;
		}else{
			signCert = CertUtil.getCertFromSM2(pfxFileData);
			// 步骤3 获得私钥对象
			privateKey = KeyUtil.getPrivateKeyFromSM2(pfxFileData, pfxFilePwd);
			signAlg = Mechanism.SM3_SM2;
		}
		
		// 组装签名报文
		StringBuilder stringBuilder = new StringBuilder();
		stringBuilder.append(signXml);

		Signature signKit = new Signature();
		byte[] sourceData = stringBuilder.toString().getBytes("UTF8");
		
		byte[] signedData = signKit.p7SignMessageDetach(signAlg, sourceData, privateKey, signCert, session);
		String singtext = new String(signedData);

		WriteBankLogLn("签名返回的结果：" + singtext);

		return singtext;
	}*/
}
